package logger

import (
	"context"
	"fmt"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
	"mychat/internal/common/utils"
)

type baselogger struct {
	Logger
	tag      LoggerTag
	logLevel Level
}

func (l *baselogger) WithCustomTag(tag LoggerTag) Logger {
	nl := *l
	nl.tag = tag
	nl.Logger = &nl
	return &nl
}

func (l *baselogger) WithCustomStrTag(tagstr string) Logger {
	return l.WithCustomTag(LoggerTag(tagstr))
}

func (l *baselogger) GetLogger() Logger {
	return l.Logger
}

func (l *baselogger) LogEntry(logEntry map[string]any) {
	fmt.Println("need implemented")
	return
}

func (l *baselogger) log(tag LoggerTag, logLevel Level, fmtStr string, args ...any) {
	if l.logLevel > logLevel {
		return
	}
	message := safeSprintf(fmtStr, args...)
	msg, logEntry := parseLogMsg(message)
	filename, lineno, funcName := utils.GetCaller(2)
	callerInfo := strings.Join([]string{filename, strconv.Itoa(lineno), funcName}, "-")
	logEntry["logger_caller"] = callerInfo
	logEntry["logger_tag"] = tag
	logEntry["message"] = msg
	logEntry["logger_level"] = logLevel.String()
	l.Logger.LogEntry(logEntry)
}

func (l *baselogger) FatalCtx(ctx *gin.Context, fmtStr string, args ...any) {
	fmtStr, args = preprocessLogArgs(ctx, fmtStr, args)
	message := safeSprintf(fmtStr, args...)
	l.log(l.tag, FATAL, message)
	captureErrorMessage(message)
}

func (l *baselogger) ErrorCtx(ctx *gin.Context, fmtStr string, args ...any) {
	fmtStr, args = preprocessLogArgs(ctx, fmtStr, args)
	message := safeSprintf(fmtStr, args...)
	l.log(l.tag, ERROR, message)
	captureErrorMessage(message)
}

func (l *baselogger) WarningCtx(ctx *gin.Context, fmtStr string, args ...any) {
	fmtStr, args = preprocessLogArgs(ctx, fmtStr, args)
	l.log(l.tag, WARNING, fmtStr, args...)
}

func (l *baselogger) InfoCtx(ctx *gin.Context, fmtStr string, args ...any) {
	fmtStr, args = preprocessLogArgs(ctx, fmtStr, args)
	l.log(l.tag, INFO, fmtStr, args...)
}

func (l *baselogger) DebugCtx(ctx *gin.Context, fmtStr string, args ...any) {
	fmtStr, args = preprocessLogArgs(ctx, fmtStr, args)
	l.log(l.tag, DEBUG, fmtStr, args...)
}

func (l *baselogger) Fatal(ctx context.Context, fmtStr string, args ...any) {
	fmtStr, args = preprocessLogArgs(ctx, fmtStr, args)
	message := safeSprintf(fmtStr, args...)
	l.log(l.tag, FATAL, message)
	captureErrorMessage(message)
}

func (l *baselogger) Error(ctx context.Context, fmtStr string, args ...any) {
	fmtStr, args = preprocessLogArgs(ctx, fmtStr, args)
	message := safeSprintf(fmtStr, args...)
	l.log(l.tag, ERROR, message)
	captureErrorMessage(message)
}

func (l *baselogger) Warning(ctx context.Context, fmtStr string, args ...any) {
	fmtStr, args = preprocessLogArgs(ctx, fmtStr, args)
	l.log(l.tag, WARNING, fmtStr, args...)
}

func (l *baselogger) Info(ctx context.Context, fmtStr string, args ...any) {
	fmtStr, args = preprocessLogArgs(ctx, fmtStr, args)
	l.log(l.tag, INFO, fmtStr, args...)
}

func (l *baselogger) Debug(ctx context.Context, fmtStr string, args ...any) {
	fmtStr, args = preprocessLogArgs(ctx, fmtStr, args)
	l.log(l.tag, DEBUG, fmtStr, args...)
}
